package net;

import interfaces.ICardManagement;
import interfaces.IClientReciever;
import interfaces.IClientSender;
import interfaces.IGameManagement;
import interfaces.IPlayerManagement;

import java.io.IOException;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;

import persistence.DataFiles;
import persistence.FilePersistenceManager;
import persistence.IPersistenceManager;
import tools.MyTools;
import valueObjects.game.Player;
import valueObjects.game.card.Card;
import valueObjects.game.card.door.CharacterClassCard;
import valueObjects.game.card.door.CharacterRaceCard;
import valueObjects.game.card.door.CurseCard;
import valueObjects.game.card.door.MonsterCard;
import valueObjects.game.card.treasure.BuffCard;
import valueObjects.game.card.treasure.DebuffCard;
import valueObjects.game.card.treasure.EquipmentCard;
import valueObjects.game.card.treasure.MiscellaneousCard;
import exception.equipment.NotEquipable;
import exception.game.GameNotSavedException;
import exception.player.CurseInvalidException;
import exception.player.NotEqualPasswordException;
import exception.player.PlayerAlreadyExistsException;
import exception.player.PlayerNotSavedException;

/**
 * This class is for managing the game
 */
public class GameManagement extends UnicastRemoteObject implements Serializable, IGameManagement {

	private static final long serialVersionUID = 1L;

	private ICardManagement cManager;
	
	private IPlayerManagement pMananger;
	
	private static final short WINLEVEL = 10;

	private transient IPersistenceManager loader = new FilePersistenceManager();

	private short round;

	private List<IClientSender> sessions = new ArrayList<IClientSender>();

	private List<Player> playersHelp = new ArrayList<Player>();
	
	private List<IClientSender> playersInteract = new ArrayList<IClientSender>();

	private int askedForHelp = 0;	

	/**
	 * Constructor with datafiles where the main resources are stored and the playerManager
	 * @param cardManagement
	 * @param pManager
	 * @throws IOException
	 * @throws ClassNotFoundException
	 * @throws InterruptedException 
	 */
	public GameManagement(ICardManagement cardManagement, IPlayerManagement pManager) throws IOException,
	ClassNotFoundException, InterruptedException, RemoteException {
		this.cManager = cardManagement;
		this.pMananger = pManager;
		this.round = 1;
	}

	/**
	 * Returns the round of the game.
	 * @return the round
	 */
	public short getRound() throws RemoteException{
		return round;
	}

	/**
	 * Sets the round after a player is finished.
	 * @param round the round to set
	 */
	public void setRound(short round) throws RemoteException {
		this.round = round;
	}

	/**
	 * Adds a miscellaneous card to others list
	 * @param eCard
	 * @throws NotEquipable 
	 */
	public void addMiscellaneuos(Player p, MiscellaneousCard eCard) throws NotEquipable, RemoteException{
		if(p.hasClassOrRace(eCard)){
			p.getOthers().add(eCard);
		} else {
			throw new NotEquipable(p, eCard);
		}
	}

	/**
	 * Changes players equipment in a specific slot
	 * @param type
	 * @param changeECard
	 * @throws NotEquipable 
	 */
	public void changeEquipment(Player p, String type, EquipmentCard changeECard) throws NotEquipable, RemoteException{
		if(!(type.equals(EquipmentCard.ARMOR) || 
				type.equals(EquipmentCard.FEET) || 
				type.equals(EquipmentCard.HELMET) || 
				type.equals(EquipmentCard.ONE_HAND) || 
				type.equals(EquipmentCard.TWO_HAND) || 
				type.equals(""))){
			throw new NotEquipable(p, changeECard);
		}
		if(!p.hasClassOrRace(changeECard)){
			throw new NotEquipable(p, changeECard);
		}
		if(p.getEquipmentSlots().get(type) != null){
			p.getEquipmentSlots().put(type, changeECard);
		} else {
			p.getEquipmentSlots().put(type, changeECard);
		}
	}

	/**
	 * Curses the player with the given curse card.
	 * @param c
	 * @throws CurseInvalidException
	 */
	public void curse(CurseCard c, Player p) throws CurseInvalidException, RemoteException{

		if(c.getCurse().equals("level")){
			// if the cursecard efects the level
			if(p.getLevel() > 1){
				short lvl = p.getLevel();
				lvl--;
				p.setLevel(lvl);
			}
		} else if(c.getCurse().equals("biggestBonus")){
			// if the cursecard efects the biggest bonus
			// first loojing through others
			MiscellaneousCard mToRemove = null;
			short bonus = 0;
			if(!p.getOthers().isEmpty()){
				bonus = p.getOthers().get(0).getValue();
				for (MiscellaneousCard card : p.getOthers()) {
					if(card.getValue() >= bonus){
						bonus = card.getValue();
						mToRemove = card;
					}
				}
			}
			// second looking throgh the equiment
			EquipmentCard eToRemove = null;
			for (String type : p.getEquipmentSlots().keySet()) {
				EquipmentCard eCard = (EquipmentCard) p.getEquipmentSlots().get(type);
				if(eCard != null && eCard.getValue() >= bonus){
					eToRemove = eCard;
				}
			}
			// set equip to null
			if(eToRemove != null){
				p.getEquipmentSlots().put(eToRemove.getSlot(), null);
			} else if(mToRemove != null){
				p.getOthers().remove(mToRemove);
			} else {
				// if nothing happend
				throw new CurseInvalidException(c, p);
			}
		} else {
			// removing equipment depending on curse
			if(p.getEquipmentSlots().get(c.getCurse()) != null){
				p.getEquipmentSlots().put(c.getCurse(), null);
			} else {
				throw new CurseInvalidException(c, p);
			}
		}
	}

	/**
	 * Returns the current player
	 * @return Player currentPlayer
	 * @throws RemoteException 
	 */
	public Player getCurrentPlayer() throws RemoteException{
		return this.pMananger.getCurrentPlayer();
	}
	
	/**
	 * @return the pickUpStackDoorCards
	 * @throws RemoteException 
	 */
	public Vector<Card> getPickUpStackDoorCards() throws RemoteException {
		return this.cManager.getPickUpStackDoorCards();
	}
	

	/**
	 * Adds a card to the deposit stack of door cards
	 * @param c
	 * @throws RemoteException 
	 */
	public void addDepositDoorCard(Card c) throws RemoteException {
		this.cManager.addDepositDoorCard(c);
	}

	/**
	 * Adds a card to the treasure stack of door cards
	 * @param c
	 * @throws RemoteException 
	 */
	public void addDepositTreasureCard(Card c) throws RemoteException {
		this.cManager.addDepositTreasureCard(c);
	}

	/**
	 * Saves the game by the given filename
	 * @param fileName
	 * @throws GameNotSavedException
	 * @throws RemoteException 
	 */
	public void save(String fileName) throws GameNotSavedException, RemoteException{
		String file = DataFiles.generateFile(this.pMananger.getCurrentPlayers(), fileName);
		try {
			this.loader.openForWritingSer(file);
			this.loader.saveGame(this);
			this.loader.close();
		} catch (IOException e) {
			this.loader.close();
			throw new GameNotSavedException(file);
		}
	}

	/**
	 * calculate the end of the fight
	 * 
	 * @param currentPlayer
	 * @param currentMonster
	 * @return true or false
	 * 
	 */
	public boolean combat(Player currentPlayer, MonsterCard currentMonster) throws RemoteException{
		boolean win = false;
		short monsterLevel = currentMonster.getMonsterLevel();
		short combatLevel = currentPlayer.getCombatLevel();
		if (monsterLevel < combatLevel) {
			win =  true;
		}
		return win;
	}

	/**
	 * Returns true if the Player has something to equip on his hand cards
	 * 
	 * @param player
	 * @return true of false
	 */
	public boolean canEquip(Player player) throws RemoteException{
		short result = 0;
		for (Card handCards : player.getHandCards()) {
			if(handCards instanceof EquipmentCard && player.hasClassOrRace((EquipmentCard) handCards)){
				result++;
			} else if(handCards instanceof CharacterClassCard || handCards instanceof CharacterRaceCard){
				result++;
			}
		}
		return result > 0;
	}

	/**
	 * Returns true if the calculated end of the interaction is true.
	 * Also if the final combatlvl of the player is higher then monster+cardsinteract
	 * @param player
	 * @param monster
	 * @param vector
	 * 
	 *            return true or false
	 */
	public boolean interaction(Player player, Card monster) throws RemoteException{
		boolean won = false;
		short combatLvlAllEnemys = ((MonsterCard) monster).getMonsterLevel();

		for (IClientSender playerInteract : sessions) {
			for (Card card : playerInteract.getPlayer().getCardsInteractAgainst()) {
				if(card instanceof MonsterCard){
					combatLvlAllEnemys += ((MonsterCard)card).getScoreLevel();
				} else if(card instanceof BuffCard){
					combatLvlAllEnemys += ((BuffCard)card).getCombatLevel();
				}
			}
		}

		if(player.getCombatLevel() > combatLvlAllEnemys){
			won = true;
		}

		return won;
	}

	/**
	 * Calculates the result of the fight by the given players, who want to help.
	 * @param player
	 * @param doorCard
	 * @param currentPlayers
	 * @return
	 */
	public boolean interactionHelp(Player player, Card doorCard) throws RemoteException{
		this.askedForHelp ++;
		boolean won = false;
		short combatLvlAllEnemys = ((MonsterCard) doorCard).getMonsterLevel();
		short combatLvlPlayer = player.getCombatLevel();
		for (Player playerInteract : playersHelp) {
			for (Card card : playerInteract.getCardsInteractHelp()) {
				combatLvlPlayer += ((BuffCard) card).getCombatLevel();
			}
			combatLvlPlayer += playerInteract.getCombatLevel();
		}
		if(combatLvlPlayer>combatLvlAllEnemys)
			won = true;

		return won;
	}

	/**
	 * calculates the rewards of the Fight
	 * 
	 * @param player
	 * @param monster
	 * @return 
	 * @throws RemoteException 
	 * 
	 */
	public void generateRewards(Player player, MonsterCard monster) throws RemoteException {
		short treasures = monster.getCountOfTreasures();
		short updateLvl = monster.getScoreLevel();
		for (IClientSender p : sessions) {
			for (Card c : p.getPlayer().getCardsInteractAgainst()) {
				if(c instanceof MonsterCard){
					MonsterCard mCard = (MonsterCard) c;
					treasures += mCard.getCountOfTreasures();
					updateLvl += mCard.getScoreLevel();
				}
			}
		}
		this.removeInteraction();
		player.updateLevelBy(updateLvl);
		for (int i = 0; i < treasures; i++) {
			player.addCard(getOneCardFromTreasurePickUpStack());
		}
		for(int i=0; i < sessions.size(); i++) {
			ClientSession tmp = (ClientSession)sessions.get(i);
			if(tmp.getPlayer().equals(player)){
				try {
					tmp.setPlayer(player);
					tmp.getClientHandle().recieveUpdateHandCards(player);
				} catch(RemoteException ex) {
					System.out.println("removing.");
					removeSession(tmp);
					i--; // Da nun alle Clients in Liste einen Platz nach unten rutschen ...
				}
			} 
		}
		sendMessage(player + " hat das Monster " + monster.getLabel() + " besiegt.");
		this.playersHelp = new ArrayList<Player>();
	}

	/**
	 * returns true if one of the Players in the currentPlayers is over the
	 * GameManagement.winLevel
	 * 
	 * @param player
	 * @return true of false
	 * @throws RemoteException 
	 * 
	 */
	public boolean playerWon() throws RemoteException {
		boolean pWon = false;
		for (IClientSender player : sessions) {
			if (player.getPlayer().getLevel() >= GameManagement.WINLEVEL)
				pWon = true;
		}
		return pWon;
	}

	/**
	 * returns true if the Player can escape
	 * 
	 * @param player
	 * @return true of false
	 * 
	 */
	public boolean escapePossible(Player player) throws RemoteException{
		boolean esc = false;
		short playersDice = (short) MyTools.myRandom(1, 6);
		if (player.getEscapeLevel() < playersDice) {
			esc = true;
		}
		return esc;
	}

	/**
	 * Saving new Players.
	 * @param p
	 * @param sourceFile
	 * @return 
	 * @return
	 * @throws PlayerNotSavedException 
	 * @throws NotEqualPasswordException 
	 * @throws PlayerAlreadyExistsException 
	 * @throws RemoteException 
	 */
	public void saveNewPlayer(String username, String passwordF, String passwordS) throws PlayerAlreadyExistsException, NotEqualPasswordException, PlayerNotSavedException, RemoteException {
		this.pMananger.saveNewPlayer(username, passwordF, passwordS);
	}

	/**
	 * Checks whether Player p is current player
	 * @param p
	 * @return boolean
	 * @throws RemoteException 
	 */
	public boolean isCurrentPlayer(Player p) throws RemoteException {
		return this.pMananger.isCurrentPlayer(p);
	}

	/**
	 * Checks whether the given player has some DebuffCards on his hands
	 * @return boolean
	 */
	public boolean canInteractAgainst(Player p) throws RemoteException{
		for (Card c : p.getHandCards()) {
			if(c instanceof DebuffCard || c instanceof MonsterCard){
				return true;
			}
		}
		return false;
	}

	/**
	 * Checks whether the given player has some BuffCards on his hands
	 * @param p
	 * @return
	 */
	@Override
	public boolean canInteractHelp(Player p) throws RemoteException{
		for (Card c : p.getHandCards()) {
			if(c instanceof BuffCard){
				return true;
			}
		}
		return false;
	}

	public List<IClientSender> getSessions(){
		return this.sessions;
	}
	
	/**
	 * Returns a list with the current players
	 * @throws RemoteException 
	 * @return Player
	 */
	@Override
	public Vector<Player> getCurrentPlayers() throws RemoteException {
		return this.pMananger.getCurrentPlayers();
	}
	/**
	 * Returns one Card from TreasurePickUpStack
	 * @throws RemoteException
	 * @return Card
	 */
	@Override
	public Card getOneCardFromTreasurePickUpStack() throws RemoteException {
		return this.cManager.getOneCardFromTreasurePickUpStack();
	}
	/**
	 * Returns one Card from DoorPickUpStack
	 * @throws RemoteException
	 * @return Card
	 */
	@Override
	public Card getOneCardFromDoorPickUpStack() throws RemoteException {
		return this.cManager.getOneCardFromDoorPickUpStack();
	}

	/**
	 * Adds adds a player to the currentPlayer list
	 * @param player
	 * @throws RemoteException
	 */
	@Override
	public void addCurrentPlayer(Player player) throws RemoteException {
		this.pMananger.addCurrentPlayer(player);
	}

	/**
	 * Returns true if the current Player can Handle the Combat or has a buffCard.
	 * @param player
	 * @return true of false
	 * 
	 */
	@Override
	public boolean canHandle(Player player) throws RemoteException {
		boolean canHandle = false;
		for (Card card : player.getHandCards()) {
			if (card instanceof BuffCard)
				canHandle = true;
		}
		
		return canHandle;
	}

	/**
	 * Returns a Vector-List of all Players
	 * @throws RemoteException
	 * @return listOfPlayers
	 */
	@Override
	public Vector<Player> getListOfPlayers() throws RemoteException {
		return this.pMananger.getListOfPlayers();
	}

	/**
	 * Adding an new Player to the list
	 * @throws RemoteException
	 */
	@Override
	public void addNewPlayer(Player player) throws RemoteException {
		this.pMananger.addNewPlayer(player);
	}

	/**
	 * Returns the next player
	 * @param currentPlayer
	 * @return
	 */
	@Override
	public IClientSender getNextPlayer(Player currentPlayer) throws RemoteException {
		for (short i = 0; i < this.pMananger.getCurrentPlayers().size(); i++) {
			if(this.sessions.get(i).getPlayer().equals(currentPlayer)){
				try {
					return this.sessions.get(i + 1);
				} catch (Exception e) {
					return this.sessions.get(0);
				}
			}
		}
		return null;
	}

	/**
	 * Load the lost of the Players
	 * @throws RemoteException
	 * @throws ClassNotFoundException
	 * @throws RemoteException
	 */
	@Override
	public void loadListOfPlayers() throws IOException, ClassNotFoundException,
			RemoteException {
		this.pMananger.loadListOfPlayers();
	}

	/**
	 * Returns all TreasureCards
	 * @throws RemoteException
	 * @return Vector<Card>
	 */
	@Override
	public List<Card> getTreasureCards() throws RemoteException {
		return this.cManager.getTreasureCards();
	}

	/**
	 * Returns all DoorCards
	 * @throws RemoteException
	 * @return Vector<Card>
	 */
	@Override
	public List<Card> getDoorCards() throws RemoteException {
		return this.cManager.getDoorCards();
	}

	/**
	 * Returns the PickUpstack for TreasureCards
	 * @throws RemoteException
	 * @return Vector<Card>
	 */
	@Override
	public Vector<Card> getPickUpStackTreasureCards() throws RemoteException {
		return this.cManager.getPickUpStackTreasureCards();
	}

	/**
	 * setting the Currentplayer by given Player
	 * @throws RemoteException
	 */
	@Override
	public void setCurrentPlayer(Player p) throws RemoteException {
		this.pMananger.setCurrentPlayer(p);
	}
	
	// SERVERSIDE	
	
	/**
	 * Constructor
	 * @param p
	 * @param handle
	 * @throws RemoteException
	 * @return s
	 */
	@Override
	public IClientSender createSession(Player p, IClientReciever handle)
			throws RemoteException {
		System.out.println("create client session " + p.getName());
		IClientSender s = new ClientSession(p, this, handle);
		sessions.add(s);
		return s;
	}

	/**
	 * When a player is finished with his turn. Sets next players as current player.
	 * @param p
	 * @param card 
	 * @throws RemoteException 
	 */
	public void finish(Player p) throws RemoteException, IOException{
		if(p.getLevel() == WINLEVEL){
			sendWin(p);
		}
		this.pMananger.finish(p);
		for(int i=0; i < sessions.size(); i++) {
			((ClientSession)sessions.get(i)).getClientHandle().finish(this.getCurrentPlayer());
		}
		this.askedForHelp = 0;
	}
	
	public void sendWin(Player p) throws RemoteException {
		for(int i=0; i < sessions.size(); i++) {
			((ClientSession)sessions.get(i)).getClientHandle().sendWin(p);
		}
	}

	/**
	 * Delivers the given card to the clients in the session
	 * @throws RemoteException
	 */
	public void postCard(Card card) throws RemoteException {
		for(int i=0; i < sessions.size(); i++) {
			((ClientSession)sessions.get(i)).getClientHandle().recieveCard(card);
		}
	}
	/**
	 * Delivers the given message to the clients in the session
	 * @param nick
	 * @param message
	 * @throws RemoteException
	 */
	public void postMessage(String nick, String message) throws RemoteException {
		for(int i=0; i < sessions.size(); i++) {
			((ClientSession)sessions.get(i)).getClientHandle().receiveMessage(nick, message);
		}
	}
	/**
	 * Delivers the start of the Game to the clients in the session
	 * @throws RemoteException
	 */
	public void startGame() throws RemoteException{
		for(int i=0; i < sessions.size(); i++) {
			((ClientSession)sessions.get(i)).getClientHandle().recieveStartGame();
		}
	}
	
	/**
	 * Removes the session when the Clients sends Quit
	 * @param session
	 * @throws RemoteException
	 */
	@Override
	public void removeSession(IClientSender session) throws RemoteException {
		System.out.println("remove client session " + session.getPlayer().getName());
		this.pMananger.getCurrentPlayers().remove(session.getPlayer());
		sessions.remove(session);
	}
	/**
	 * Delivers the given askForInteraction to the clients in the session und returns true, if a player wants to Interact
	 * @param player
	 * @throws RemoteException
	 * @return result
	 */
	public boolean askForInteraction(Player player) throws RemoteException, InterruptedException {
		boolean result = false;
		ClientSession tmp;
		for(int i=0; i < sessions.size(); i++) {
			tmp = (ClientSession)sessions.get(i);
			if(!tmp.getPlayer().equals(player) && this.canInteractAgainst(tmp.getPlayer())){
				IClientSender recieveInteraction = tmp.getClientHandle().recieveInteraction(player);
				if(recieveInteraction != null){
					this.playersInteract.add(recieveInteraction);
					waitForCard(tmp);
				} else {
					tmp.getClientHandle().waitForCad();
				}
			}
		}
		return result;
	}
	
	/**
	 * removes the Interaction 
	 * @throws RemoteException
	 */
	@Override
	public void removeInteraction() throws RemoteException {
		this.pMananger.removeInteraction();
	}

	/**
	 * Delivers the given askForHelp to the clients in the session und returns true, if a player wants to Interact
	 * @param player
	 * @throws RemoteException
	 * @return result
	 */
	public boolean askForHelp(Player player) throws RemoteException, InterruptedException {
		if(this.askedForHelp >= 3){
			return false;
		}
		boolean result = false;
		ClientSession tmp;
		for(int i=0; i < sessions.size(); i++) {
			tmp = (ClientSession)sessions.get(i);
			if(!tmp.getPlayer().equals(player) && !inList(tmp.getPlayer())){
				Player recieveAskForHelp = tmp.getClientHandle().recieveAskForHelp(player);
				if(recieveAskForHelp != null){
					this.playersHelp.add(recieveAskForHelp);
					result = true;
				} 
			}
		}
		return result;
	}

	/**
	 * Checks whether given player is in the playershelp list
	 * @param player
	 * @return
	 */
	private boolean inList(Player player) {
		for (Player p : this.playersHelp) {
			if(p.equals(player)){
				return true;
			}
		}
		return false;
	}

	/**
	 * Delivers the result of badThings to the Currentplayer
	 * @param clientsession
	 * @param c
	 * @throws RemoteException
	 */
	public void flee(ClientSession clientSession, MonsterCard c) throws RemoteException {
		for (IClientSender p : this.sessions) {
			for (Card card : p.getPlayer().getCardsInteractAgainst()) {
				if(card instanceof MonsterCard){
					int rnd = MyTools.myRandom(1, 6);
					if(rnd <= 3){
						this.badThings(clientSession, (MonsterCard)card);
					} else {
						this.sendMessage(clientSession.getPlayer() + " konnte erfolgreich vor " + c.getLabel() + " fliehen.");
					}
				}
			}
		}
		int rnd = MyTools.myRandom(1, 6);
		if(rnd <= 3){
			this.badThings(clientSession, c);
		} else {
			this.sendMessage(clientSession.getPlayer() + " konnte erfolgreich vor " + c.getLabel() + " fliehen.");
		}
	}

	/**
	 * UPdates the player by the given monsterCards BadThings
	 * @param c
	 * @param clientSession
	 * @throws RemoteException
	 */
	private void badThings(ClientSession clientSession, MonsterCard c) throws RemoteException {
		Player p = clientSession.getPlayer();
		p.updateLevelBy((short) -2);
		sendMessage("Spieler " + p + " verliert maximal 2 Level.");
		clientSession.getClientHandle().recieveBadThings();
	}

	/**
	 * Delivers the given SYSTEM message to all clients in this session
	 * @param message
	 * @throws RemoteException
	 */
	@Override
	public void sendMessage(String message) throws RemoteException {
		for(int i=0; i < sessions.size(); i++) {
			ClientSession tmp = (ClientSession)sessions.get(i);
			tmp.getClientHandle().receiveMessage("System", message);
		}
	}
	/**
	 * Delivers the given USERS message to all clients in this session
	 * @param message
	 * @param session
	 * @throws RemoteException
	 */
	@Override
	public void sendMessage(IClientSender session, String message) throws RemoteException {
		for(int i=0; i < sessions.size(); i++) {
			ClientSession tmp = (ClientSession)sessions.get(i);
			tmp.getClientHandle().receiveMessage(session.getPlayer().getName(), message);
		}
	}

	/**
	 * Asks other players if they want to save the game
	 * @param clientSession
	 * @return
	 * @throws RemoteException
	 */
	public boolean askForSave(ClientSession clientSession) throws RemoteException {
		for(int i=0; i < sessions.size(); i++) {
			ClientSession tmp = (ClientSession)sessions.get(i);
			if(!tmp.getPlayer().equals(clientSession.getPlayer())){
				if(!tmp.getClientHandle().recieveAskForSave(clientSession.getPlayer())){
					return false;
				}
			}
		}
		return true;
	}

	@Override
	public boolean playedCard(IClientSender clientSession) throws RemoteException {
		for (IClientSender p : this.playersInteract) {
			while(!((ClientSession)p).getClientHandle().cardPlayed()){}
		}
		return true;
	}

	@Override
	public void waitForCard(IClientSender session) throws RemoteException {
		for (IClientSender sess : this.sessions) {
			if(!sess.getPlayer().equals(session.getPlayer())){
				((ClientSession)sess).getClientHandle().recieveCardInteract();
			} else {
				((ClientSession)sess).getClientHandle().waitForCad();
			}
		}
	}

}